/**
  *****************************************************************************
  * @file    realsense.h
  * @author  DeQian Yan
  * @version V1.0.1-AGV
  * @date    2019.08.14
  * @brief   realsense双目摄像头函数头文件
  *****************************************************************************
  * 版本说明:
  *  V1.0.0 realsense摄像头基本功能例程
  */
#ifndef REALSENSE_CV_H_
#define REALSENSE_CV_H_

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fstream>
#include <errno.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <math.h>
#include <algorithm>
#include <librealsense2/rs.hpp>

using namespace std;
using namespace cv;

const int FRAME_WIDTH = 1280;
const int FRAME_HEIGHT = 720;
const int FRAME_FPS = 15;

#define PC_Mode

#define Video_Output        0   //录像模式
#define Display_Mode        1   //测试图像显示模式

#define VIDEO_FILE_PATH     "./video/"

#if Video_Output
#include <opencv2/video.hpp>
#include <opencv2/videoio.hpp>
#include "videoEncoder.h"

#define FRAME_FPS_INDICT    13  //预测的每秒帧数
//#define VIDEO_SAVE_INTERVAL 5    //5min切换一个视频
#endif

#define KINECT2_MAX_LISTEN_TIME    (10 * 1000)  //监听接收图像的超时时间，单位ms
#define KINCET2_SEND_INFO_TIME     (50 * 1000) //发送状态间隔的时间

#define PI                      3.141592653
#define FLOAT_MINIMUM           0.00001
#define MEDIAN_GROUP            3
#define AVER_KERNEL_SIZE        3
#define FILTER_CRITICAL_VALUE   2000.0

#if Display_Mode
#define X_DIVIDE            1
#define Y_DIVIDE            1
#else
#define X_DIVIDE            4   //x坐标抽样值(设定抽样值能节省时间，抽样值对全体有效)
#define Y_DIVIDE            4   //y坐标抽样值
#endif

#define X_ZONE_NUM          32 //X轴划分区间的个数, 14
#define Y_ZONE_NUM          3 //Y轴划分区间的个数,
#define Y_TOP_RATE          1 //Y轴上方屏蔽部分比率. (1.0/8)
#define Y_BOT_RATE          1 //Y轴下方屏蔽部分比率. (1.0/8)
#define AVR_LIMIT_RATE      (1/3) //同一区域去除小于平均值*AVR_LIMIT_RATE 的值

#define WARN_LIMIT          1000    //能否通行的深度值界限。单位mm,范围在500~4500之间
#define MAX_DETECT_PACK     X_ZONE_NUM * Y_ZONE_NUM //最大检测障碍物信息组数
#define MIN_DETECT_AREA     500

typedef struct depth_info_pack_type{
    float min_depth;
    float x_distance;
} depth_info_pack;

// 深度摄像头内参结构
struct CAMERA_INTRINSIC_PARAMETERS
{
    double cx = 640;
	double cy = 360;
	double fx = 640.059;
	double fy = 640.059;
	double scale = 1;
};

typedef struct depth_info_pack_mix_type
{
    depth_info_pack info_pack[MAX_DETECT_PACK];
} depth_info_mix;

class RealsenseDetector
{
public:
    RealsenseDetector(int movementFd_in);
    ~RealsenseDetector();
    int open_device();
    int stop_device();
    int start_device();
    int close_device();
    int get_status();
    int process_one_frame();//replace the run

    void get_threshold_mask(Mat &src, Mat& thr, int thr_min, int thr_max);
    int filer_noise_test(Mat &src, int element_size, double val_prop);
	bool point_angle_trans(cv::Mat& src, int angle, int height, int height_max);
	int roi_cloud(cv::Mat& src, cv::Mat& src_roi, int cam_heigh, int cam_side);
    bool fall_down_obj(Mat &src, int element_size, double val_prop);
    bool ward_cam_obj(Mat &dep_src, double inval_pre);
    int process_depth_data(Mat &depth);

    int get_range(int index, int *x1, int *x2, int *y1, int *y2);
	void get_xrange(int xindex, int *x1, int *x2);
	void get_yrange(int yindex, int *y1, int *y2);

    int Robot_Send_Kinect_Info(depth_info_mix &mix);
    uchar cal_sum(uchar *data, int n);
    void get_kinect_info_pack(depth_info_mix &info_pack);
    static int depth_to_gray(Mat &src, Mat &dest);

private:
    //私有变量
    depth_info_mix mix_pack;
	CAMERA_INTRINSIC_PARAMETERS cam_para;

    int dev_status = -1;
    int m_movementFd = -1;
#ifdef Video_Output
//    VideoWriter color_writer;
//    videoThread myVideo;
#endif
    rs2::pipeline pipe;
    rs2::config cfg;
};

#endif
